package jwt

import (
	"crypto/rsa"
	"fmt"
	"time"

	"github.com/dgrijalva/jwt-go"
)

type JWTTokenGenerate struct {
	privateKey *rsa.PrivateKey
	issuer     string
	nowFunc    func() time.Time
}

func NewJWTTokenGen(issuer string, privateKey *rsa.PrivateKey) *JWTTokenGenerate {
	return &JWTTokenGenerate{
		privateKey: privateKey,
		issuer:     issuer,
		nowFunc:    time.Now,
	}
}

func (j *JWTTokenGenerate) GenerateToken(username string, expireTime int) (string, error) {
	nowTime := j.nowFunc().Unix()
	token := jwt.NewWithClaims(jwt.SigningMethodRS512, jwt.StandardClaims{
		Issuer:    j.issuer,
		IssuedAt:  nowTime,
		ExpiresAt: nowTime + int64(expireTime),
		Subject:   username,
	})
	return token.SignedString(j.privateKey)
}

// JWTTokenVerifier 校验token
type JWTTokenVerifier struct {
	PublicKey *rsa.PublicKey
}

func (v *JWTTokenVerifier) ParseToken(token string) (string, error) {
	// 自定义字段许使用  jwt.MapClaims{}，这里没有定义其他字段，就用jwt.StandardClaims
	jwtToken, err := jwt.ParseWithClaims(token, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
		return v.PublicKey, nil
	})

	if err != nil {
		return "", err
	}
	if !jwtToken.Valid {
		return "", fmt.Errorf("token not valid")
	}
	// 判断类型
	clm, ok := jwtToken.Claims.(*jwt.StandardClaims)
	if !ok {
		return "", fmt.Errorf("token claim is not StandardClaims")
	}

	if err = clm.Valid(); err != nil {
		return "", fmt.Errorf("claim not valid: %v", err)
	}

	return clm.Subject, nil
}
